﻿namespace UnityEditor.Graphs.AnimationBlendTree
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using UnityEditor;
    using UnityEditor.Graphs;
    using UnityEditorInternal;
    using UnityEngine;

    internal class Graph : UnityEditor.Graphs.Graph
    {
        private const float kLeafHorizontalOffset = 20f;
        private const float kNodeHeight = 50f;
        private const float kNodeHorizontalPadding = 70f;
        private const float kNodeVerticalPadding = 5f;
        private const float kNodeWidth = 200f;
        private const float kSectionVerticalPadding = 15f;
        private Dictionary<string, float> m_EventValues = new Dictionary<string, float>();
        [SerializeField]
        private BlendTree m_RootBlendTree;
        private UnityEditor.Graphs.AnimationBlendTree.Node m_RootNode;
        private float m_VerticalLeafOffset;
        [SerializeField]
        public Animator previewAvatar;

        private void ArrangeNodeRecursive(UnityEditor.Graphs.AnimationBlendTree.Node node, int depth)
        {
            if (node.isLeaf && (node.parent != null))
            {
                Rect position = node.position;
                position.y = this.m_VerticalLeafOffset;
                position.x = (depth * 270f) + 70f;
                position.x += Mathf.PingPong((node.childIndex + 0.5f) / ((float) node.parent.children.Count), 0.5f) * 20f;
                node.position = position;
                this.m_VerticalLeafOffset += position.height + 5f;
            }
            else if (node.children.Count != 0)
            {
                float positiveInfinity = float.PositiveInfinity;
                float negativeInfinity = float.NegativeInfinity;
                foreach (UnityEditor.Graphs.AnimationBlendTree.Node node2 in node.children)
                {
                    this.ArrangeNodeRecursive(node2, depth + 1);
                    positiveInfinity = Mathf.Min(positiveInfinity, node2.position.y);
                    negativeInfinity = Mathf.Max(negativeInfinity, node2.position.y);
                }
                Rect rect2 = node.position;
                rect2.y = (positiveInfinity + negativeInfinity) * 0.5f;
                rect2.x = (depth * 270f) + 70f;
                node.position = rect2;
                this.m_VerticalLeafOffset += 15f;
            }
        }

        public void AutoArrangeNodePositions()
        {
            this.m_VerticalLeafOffset = 5f;
            this.ArrangeNodeRecursive(this.m_RootNode, 0);
        }

        public void BuildFromBlendTree(BlendTree blendTree)
        {
            this.Clear();
            if (blendTree != null)
            {
                this.CreateNodeFromBlendTreeRecursive(blendTree, null);
                this.PopulateEventValues();
                this.AutoArrangeNodePositions();
            }
        }

        public override void Clear()
        {
            base.Clear();
            this.m_EventValues.Clear();
            this.m_RootBlendTree = null;
            this.m_RootNode = null;
        }

        private void CreateEmptySlot(UnityEditor.Graphs.AnimationBlendTree.Node parentNode)
        {
            parentNode.AddOutputSlot(string.Empty);
        }

        private UnityEditor.Graphs.AnimationBlendTree.Node CreateNode(Motion motion, string name)
        {
            UnityEditor.Graphs.AnimationBlendTree.Node node = UnityEditor.Graphs.Node.Instance<UnityEditor.Graphs.AnimationBlendTree.Node>();
            node.hideFlags = HideFlags.HideAndDontSave;
            node.name = name;
            node.motion = motion;
            node.position = new Rect(0f, 0f, 200f, 50f);
            this.AddNode(node);
            return node;
        }

        private void CreateNodeFromAnimationClip(AnimationClip clip, UnityEditor.Graphs.AnimationBlendTree.Node parentNode)
        {
            UnityEditor.Graphs.AnimationBlendTree.Node node = this.CreateNode(clip, clip.name);
            node.parent = parentNode;
            Slot fromSlot = parentNode.AddOutputSlot(clip.name);
            Slot toSlot = node.AddInputSlot((parentNode.motion as BlendTree).GetName());
            this.Connect(fromSlot, toSlot);
        }

        private void CreateNodeFromBlendTreeRecursive(BlendTree blendTree, UnityEditor.Graphs.AnimationBlendTree.Node parentNode)
        {
            UnityEditor.Graphs.AnimationBlendTree.Node node = this.CreateNode(blendTree, blendTree.GetName());
            if (parentNode != null)
            {
                node.parent = parentNode;
                Slot fromSlot = parentNode.AddOutputSlot(blendTree.GetName());
                Slot toSlot = node.AddInputSlot((parentNode.motion as BlendTree).GetName());
                this.Connect(fromSlot, toSlot);
            }
            else
            {
                this.m_RootBlendTree = blendTree;
                this.m_RootNode = node;
            }
            for (int i = 0; i < blendTree.GetChildCount(); i++)
            {
                Motion motion = blendTree.GetMotion(i);
                if (motion == null)
                {
                    this.CreateEmptySlot(node);
                }
                else if (motion is BlendTree)
                {
                    this.CreateNodeFromBlendTreeRecursive(motion as BlendTree, node);
                }
                else
                {
                    if (!(motion is AnimationClip))
                    {
                        throw new NotImplementedException("Unknown Motion type:" + motion.GetType());
                    }
                    this.CreateNodeFromAnimationClip(motion as AnimationClip, node);
                }
            }
        }

        private static int FindMotionIndexOnBlendTree(BlendTree blendTree, Motion motion)
        {
            for (int i = 0; i < blendTree.GetChildCount(); i++)
            {
                if (blendTree.GetMotion(i) == motion)
                {
                    return i;
                }
            }
            return -1;
        }

        public UnityEditor.Graphs.AnimationBlendTree.Node FindNode(Motion motion)
        {
            <FindNode>c__AnonStorey14 storey = new <FindNode>c__AnonStorey14 {
                motion = motion
            };
            return Enumerable.FirstOrDefault<UnityEditor.Graphs.AnimationBlendTree.Node>(base.nodes.Cast<UnityEditor.Graphs.AnimationBlendTree.Node>(), new Func<UnityEditor.Graphs.AnimationBlendTree.Node, bool>(storey.<>m__32));
        }

        private T GetComponentFromSelection<T>() where T: Component
        {
            GameObject activeGameObject = Selection.activeGameObject;
            if (activeGameObject != null)
            {
                return activeGameObject.GetComponent<T>();
            }
            return null;
        }

        internal override UnityEditor.Graphs.GraphGUI GetEditor()
        {
            UnityEditor.Graphs.AnimationBlendTree.GraphGUI hgui = ScriptableObject.CreateInstance<UnityEditor.Graphs.AnimationBlendTree.GraphGUI>();
            hgui.graph = this;
            hgui.hideFlags = HideFlags.HideAndDontSave;
            return hgui;
        }

        public float GetEventValue(string eventName)
        {
            if (this.m_EventValues.ContainsKey(eventName))
            {
                return this.m_EventValues[eventName];
            }
            Debug.LogError("parameter name does not exist.");
            return 0f;
        }

        private T GetObjectFromSelection<T>() where T: UnityEngine.Object
        {
            return (Selection.activeObject as T);
        }

        public void PopulateEventValues()
        {
            if (this.m_RootBlendTree != null)
            {
                for (int i = 0; i < this.m_RootBlendTree.GetRecursiveBlendEventCount(); i++)
                {
                    string recursiveBlendEvent = this.m_RootBlendTree.GetRecursiveBlendEvent(i);
                    if (this.liveLink)
                    {
                        this.SetEventValue(recursiveBlendEvent, this.previewAvatar.GetFloat(recursiveBlendEvent));
                    }
                    else
                    {
                        this.SetEventValue(recursiveBlendEvent, this.m_RootBlendTree.GetInputBlendValue(recursiveBlendEvent));
                    }
                }
            }
        }

        public void RemoveNodeMotions(IEnumerable<UnityEditor.Graphs.Node> nodes)
        {
            IEnumerator<UnityEditor.Graphs.Node> enumerator = nodes.GetEnumerator();
            try
            {
                while (enumerator.MoveNext())
                {
                    UnityEditor.Graphs.Node current = enumerator.Current;
                    UnityEditor.Graphs.AnimationBlendTree.Node node2 = current as UnityEditor.Graphs.AnimationBlendTree.Node;
                    if (node2.motion != null)
                    {
                        if (node2.parent != null)
                        {
                            BlendTree blendTree = node2.parent.motion as BlendTree;
                            int index = FindMotionIndexOnBlendTree(blendTree, node2.motion);
                            blendTree.RemoveAtIndex(index);
                        }
                        BlendTree motion = node2.motion as BlendTree;
                        if ((motion != null) && MecanimUtilities.AreSameAsset(this.m_RootBlendTree, motion))
                        {
                            MecanimUtilities.DestroyBlendTreeRecursive(motion);
                        }
                    }
                }
            }
            finally
            {
                if (enumerator == null)
                {
                }
                enumerator.Dispose();
            }
        }

        public void SetEventValue(string eventName, float eventValue)
        {
            this.m_EventValues[eventName] = eventValue;
            this.SetEventValueRecursive(this.m_RootBlendTree, eventName, eventValue);
        }

        private bool SetEventValueRecursive(BlendTree blendTree, string eventName, float eventValue)
        {
            bool flag = false;
            if (blendTree.GetBlendEvent() == eventName)
            {
                blendTree.SetInputBlendValue(eventName, eventValue);
                flag = true;
            }
            for (int i = 0; i < blendTree.GetChildCount(); i++)
            {
                BlendTree motion = blendTree.GetMotion(i) as BlendTree;
                if ((motion != null) && this.SetEventValueRecursive(motion, eventName, eventValue))
                {
                    blendTree.SetInputBlendValue(eventName, eventValue);
                    flag = true;
                }
            }
            return flag;
        }

        public override void WakeUp(bool force)
        {
            base.WakeUp(force);
            this.PopulateEventValues();
        }

        public bool liveLink
        {
            get
            {
                return (((EditorApplication.isPlaying && (this.previewAvatar != null)) && this.previewAvatar.enabled) && this.previewAvatar.gameObject.activeInHierarchy);
            }
        }

        public BlendTree rootBlendTree
        {
            get
            {
                return this.m_RootBlendTree;
            }
            set
            {
                if (this.m_RootBlendTree != value)
                {
                    this.m_RootBlendTree = value;
                    this.BuildFromBlendTree(this.m_RootBlendTree);
                }
            }
        }

        [CompilerGenerated]
        private sealed class <FindNode>c__AnonStorey14
        {
            internal Motion motion;

            internal bool <>m__32(UnityEditor.Graphs.AnimationBlendTree.Node node)
            {
                return (node.motion == this.motion);
            }
        }
    }
}

